// TextSuggestDataSource
// Alex McClung
// Version 0.1
// 
// Data supplier base class for the TextSuggest object.
// 
// REQUIREMENTS: Prototype Framework v.1.5.1.1
// 
// USAGE:
var TextSuggestDataSource = Class.create();

TextSuggestDataSource.prototype = {
	
	// ========================================================================
	// Constants
	TRACE_STRING: "TextSuggestDataSource :: ",
	
	MAX_SUGGESTIONS: 10,            // Maximum number of suggestions to return
	GATEWAY_QUERY_EXPR: /\{\$Q\}/g, // {Q} Special character sequence that must
                                    // be used in the gateway URL to define 
									// where the query string should be inserted 
	
	// ========================================================================
	// Private Properties
	mData:          null,  // Array of strings. This is the full list of possible
                           // suggestable strings
	mSuggestions:   null,  // Array of strings. The list of suggested strings that
                           // have been culled from mData
	mGateway:       null,  // URI resource of the data gateway (optional)
	mGatewayMethod: 'get', // Which HTTP method to use when fetching data from the 
	                       // gateway. Either 'GET' or 'POST'
	mGatewayParams: null,  // Extra parameters to send to the server. This would 
						   // be where you can set the name of your lookup table,
						   // and anything else that is not the query string.
	
	// ========================================================================
	// Initialize
	// oParam1 (Mixed)  This can be either an Array or a String. If it is an
    //                  array, the object will use it as the list of preset
    //                  suggestions to query.
	//                  If it is a string, the object will use it as the URI of
    //                  the data gateway. You must also pass in the second
    //                  parameter in this case.
	// oParam2 (Srring) Only applicable when using a gateway. This parameter is
    //                  the HTTP method to use when querying the gateway, either 
    //                  'get' or 'post'.
	// oParam3 (Object) Extra query parameters to send to the server.
	initialize: function(oParam1, oParam2, oParam3)
	{
		// Did they pass in an array?
		if(null != oParam1 && oParam1 instanceof Array)
		{
			// They want to use a preset list of thigns
			this.setData(oParam1);
		}
		// Did they at least pass in a string?
		else if( (null != oParam1) && (typeof(oParam1) == 'string') )
		{
			// They want to use a data gateway
			this.setGateway(oParam1, oParam2, oParam3);
		}
	},
	
	// ========================================================================
	// Public Functions
	
	// ------------------------------------------------------------------------
	// Sets the list of all possible suggestable strings
	// aData (Array) Array of pre-defined suggestion strings. These strings will
	//               be queried in lookup.
	setData: function(aData)
	{
		// Grab the data
		this.mData = aData;
	},
	
	// ------------------------------------------------------------------------
	// Sets the gateway and method. Use this when you want to query a server.
	// sGateway       (String) URI of the data gateway
	// sGatewayMethod (String) Which HTTP method to use when querying the
    //                         gateway. Either 'get' or 'post'
	// oGatewayParams (Object) Extra parameters to send to the gateway.
	setGateway: function(sGateway, sGatewayMethod, oGatewayParams)
	{
		this.mGateway       = sGateway;
		this.mGatewayMethod = (null != sGatewayMethod) ? sGatewayMethod : this.mGatewayMethod;
		this.mGatewayParams = (null != oGatewayParams) ? oGatewayParams : {};
	},
	
	// ------------------------------------------------------------------------
	// Looks up suggestions matching a pattern
	// sQuery       (string) Query string (the pattern to match)
	lookup: function(sQuery)
	{
		// Do we have a gateway?
		if(null != this.mGateway)
		{
			// Use the gateway!
			this._lookupGateway(sQuery);
		}
		// We don't have a gateway
		else
		{
			// Try the array
			this._lookupArray(sQuery);
		}
	},
	
	// ------------------------------------------------------------------------
	// Gets the suggestions returned by lookup
	getSuggestions: function()
	{
		return this.mSuggestions;
	},
	
	// ========================================================================
	// Event Broadcasters
	
	// ------------------------------------------------------------------------
	// Triggered when data lookup is complete and successful
	onSuccess: function()
	{
		return;
	},
	
	// ------------------------------------------------------------------------
	// Triggered when data lookup fails
	onFailure: function()
	{
		return;
	},
	
	// ========================================================================
	// Private functions
	
	// ------------------------------------------------------------------------
	// Looks up suggestions using a data gateway
	// sQuery       (string) The pattern to match
	_lookupGateway: function(sQuery)
	{
		// Clear the suggestion list
		this.mSuggestions = [];
		
		// Add the query string to the parameters
		this.mGatewayParams.query = sQuery;
		
		// Make the AJAX request.
		new Ajax.Request(this.mGateway, 
		  {
		  	method:     this.mGatewayMethod,
			parameters: this.mGatewayParams,
			onSuccess:  this._onLookupSuccess.bind(this),
			onFailure:  this._onLookupFailure.bind(this)
		  }
		);
	},
	
	// ------------------------------------------------------------------------
	// Callback from the AJAX request; handles success condition
	_onLookupSuccess: function(transport, json)
	{
		// Grab the suggestions from the server
		this.mSuggestions = json.aSuggestions;
		
		// Fire the onSuccess event!!!
		this.onSuccess();
	},
	
	// ------------------------------------------------------------------------
	// Callback from the AJAX request; handles failure condition
	_onLookupFailure: function()
	{
		// Fire the failure event
		this.onFailure();
	},
	
	// ------------------------------------------------------------------------
	// Looks up suggestions using a simple array search
	// sQuery (string) the pattern to match
	_lookupArray: function(sQuery)
	{
		// Clear the suggestion list
		this.mSuggestions = [];
		
		// Loop through all the queries and possible suggestions, look for things
		// that begin with the search field value.
		for(var i=0; i < this.mData.length && this.mSuggestions.length < this.MAX_SUGGESTIONS; i++)
		{
			// Queries that begin with the search field value
			if(this.mData[i].indexOf(sQuery) == 0)
			{
				this.mSuggestions.push(this.mData[i]);
			}
		}
		
		// Loop through all the queries and possible suggestions, look for things
		// that contain the search field value
		for(var i=0; i < this.mData.length && this.mSuggestions.length < this.MAX_SUGGESTIONS; i++)
		{
			// Queries that include the search field value (avoid duplicate queries)
			if(this.mData[i].indexOf(sQuery) > 0)
			{
				this.mSuggestions.push(this.mData[i]);
			}
		}
		
		// We are done, fire off the onSuccess event.
		this.onSuccess();
	}
};